/*
STL string 容器
string是C++风格的字符串，本质上是一个类
string 与 char* 的区别：
  char*是一个指针
  string是一个类，内部封装了char*,管理这个字符串，是一个char*的容器
string内部封装了很多成员方法，例如查找find, 拷贝copy, 删除delete, 替换replace, 插入insert。
string管理char*所分配的内存，不用担心赋值越界和取值越界等，由类内部进行负责。

string 构造函数
  构造函数原型：
    - string(); // 创建一个空字符串 例如 string str; string(const char *); //使用字符串s初始化
    - string(const string& str); // 使用一个string对象初始化另一个string对象
    - string(int n, char c); // 使用n个字符c初始化
    - string(const char* s, int n);  // 使用字符串s 的前n 个初始化另一个字符串

string 赋值
  给string字符串进行赋值
  赋值的函数原型：
     string& operator=(const char* s);  // char* 类型字符串s 赋值给当前的字符串   string s1 = "abcd";
     string& operator=(const string& s);  // 把字符串s 赋值给当前字符串  string s2 = s1;
     string& operator=(char c);  // 把字符c 赋值给当前字符串  string s3 = 'a';
     string& assign(const char* s);  // 把字符串s 赋值给当前的字符串  string s4; s4.assign("abcde");
     string& assign(const char* s, int n);  // 把字符串s 的前n 个字符赋值给当前字符串  string s5; s5.assign("abcdefg", 3);
     string& assign(const string& s);  // 把字符串s 赋值给当前字符串  string s6; s6.assign(s5);
     string& assign(int n, char c);  // 用n个 字符c 赋值给当前字符串

string 拼接
  实现字符串末尾拼接字符串
  函数原型：
    string& operator+=(const char* s); // char* 类型字符串s 拼接到字符串后边 string s1="abc"; s1+="def";
    string& operator+=(const char c);  // 字符c 拼接到字符串后边 string s2="abc"; s2+='a';
    string& operator+=(const string& s);  // string 类型字符串s 拼接到字符串后边 string s3 = "abc"; s3+=s2;
    string& append(const char* s);  // char* 类型字符串s 连接到当前字符串后边 string s4="abc"; s4.append("def");
    string& append(const char* s, int n);  // char* 类型字符串s 的前n 个字符连接到当前字符串后边 string s5="abc"; s4.append("def", 2);
    string& append(const string &s); // 同 string& operator+=(const string& s);  操作
    string& append(const string &s, int pos, int n);  // 字符串s中从pos开始的n个字符连接到字符串末尾 

string 查找和替换
  找不到返回-1，替换的时候必须要指定从哪个位置起，多少个字符，替换为什么样的字符串
  函数原型
    int find(const string& s, int pos=0) const; // 查找s第一次出现的位置，从pos位置查找
    int find(const char* s, int pos=0) const; // 查找s第一次出现的位置，从pos位置查找
    int find(const char* s, int pos, int n) cosnt; // 从pos位置查找s 的前n 个字符第一次出现的位置
    int find(char c, int pos=0) const; // 查找字符c 第一次出现的位置
    int rfind(const string& s, int pos=0) const; // 查找s最后一次出现的位置，从pos位置查找
    int rfind(const char* s, int pos=0) const; // 查找最后一次出现的位置，从pos位置查找
    int rfind(const char* s, int pos, int n) cosnt; // 从pos位置查找s 的前n 个字符最后一次出现的位置
    int rfind(char c, int pos=0) const; // 查找字符c 最后一次出现的位置
    string& replace(int pos, int n, const string& s); // 替换从pos位置开始的n个字符为字符串s
    string& replace(int pos, int n, const char* s);  // 替换从pos位置开始的n个字符为字符串s

string 比较
  按字符的ASCII码值进行对比
  = 返回 0
  > 返回 1
  < 返回 -1
  字符串主要比较是否相等，谁打谁小没有意义
  函数原型
    int compare(const string& s) const;  // 与字符串s比较
    int compare(const char* s) const;  与字符串s比较

string 存取
  string单个字符存取方式有两种 [], at
  原型函数
    char& operator[](int n);  // 通过[]方式获取字符
    char& at(int n);  // 通过at方法获取字符

    str[i] = 'x'
    str.at(i) = 'x'

string 插入和删除
  string& insert(int pos, const char* s);  // 插入字符串s
  string& insert(int pos, const string& s);  // 插入字符串s
  string& insert(int pos, int n, char c);  // 在指定位置插入n个 字符c
  string& erase(int pos, int n=npos);  // 删除从pos位置 开始的n个 字符

string 子串
  从字符串中获取想要的子串
  函数原型
    string& substr(int pos, int n=npos) const; // 返回有pos位置开始的n个字符组成的字符串

*/

#include <iostream>
#include <string>
using namespace std;

// string 构造函数
void func1()
{
  cout << "----------------- string constructor ---------------------" << endl;
  string s1; // 创建空字符串  调用无参构造函数
  cout << "s1 = " << s1 << endl;

  const char *str = "hello world";
  string s2(str); // 把c_string转换成了string
  cout << "s2 = " << s2 << endl;

  string s3(s2); // 调用拷贝构造函数
  cout << "s3 = " << s3 << endl;

  string s4(10, 'a'); // 使用10个 a 初始化
  cout << "s4 = " << s4 << endl;

  string s5("abcdefg", 3);
  cout << "s5 = " << s5 << endl;
}

// string 赋值操作
void func2()
{
  cout << "----------------- string assignment ---------------------" << endl;
  string s1 = "abcde"; // string& operator=(const char *s);
  cout << "string& operator=(const char *s); " << "s1 = " << s1 << endl;

  string s2 = s1; // string& operator=(const string &s);
  cout << "string& operator=(const string &s); " << "s2 = " << s2 << endl;

  string s3;
  s3 = 'a'; // string& operator=(char c);
  cout << "string& operator=(char c); " << "s3 = " << s3 << endl;

  string s4;
  s4.assign("abcde"); // string& assign(const char* s);
  cout << "string& assign(const char* s); " << "s4 = " << s4 << endl;

  string s5;
  s5.assign("abcdefg", 3); // string& assign(const char* s, int n);
  cout << "string& assign(const char* s, int n);" << "s5 = " << s5 << endl;

  string s6;
  s6.assign(s5); // string& assign(const string& s);
  cout << "string& assign(const string& s); " << "s6 = " << s6 << endl;

  string s7;
  s7.assign(3, 'a'); // string& assign(int n, char c);
  cout << "string& assign(int n, char c); " << "s7 = " << s7 << endl;
}

// 字符串拼接
void func3()
{
  cout << "----------------- string splicing ---------------------" << endl;
  string s1 = "abc";
  s1 += "def";  // string& operator+=(const char* s)
  cout << "string& operator+=(const char* s); " << "s1 = " << s1 << endl;

  string s2 = "abc";
  s2 += 'd';  // string& operator+=(const char c)
  cout << "string& operator+=(const char c); " << "s2 = " << s2 << endl;

  string s3 = "ABC:";
  s3 += s2;  // string& operator+=(string& s)
  cout << "string& operator+=(string& s); " << "s3 = " << s3 << endl;

  string s4 = "abd";
  s4.append("def");  // string& append(const char* s)
  cout << "string& append(const char* s)" << "s4 = " << s4 << endl;

  string s5 = "abc";
  s5.append("defg", 2);  // string& append(const char* s, int n)  
  cout << "string& append(const char* s, int n); " << "s5 = " << s5 << endl;

  string s6 = "ABC_";
  s6.append(s5);  // string& append(string& s)
  cout << "string& append(string& s); " << "s6 = " << s6 << endl;

  string s7 = "abc";
  s7.append("defghijk", 2, 3);  // string& append(const char* s, int pos, int n)
  cout << "string& append(const char* s, int pos, int n); " << "s7 = " << s7 << endl;
}

// 字符串查找和替换
void func4()
{
  cout << "----------------- string find&replace ---------------------" << endl;
  string s1 = "abcdefg";
  int pos = s1.find("c");
  if (pos == -1)
    cout << "Don't find..." << endl;  
  else
    cout << "pos = " << pos << endl;

  string s2 = s1.replace(0, 3, "ABCDE");
  cout << "s1 = " << s1 << "string s2 = s1.replace(0, 3, ABCDE); -> " << " s2 = " << s2 << endl;
}

// 字符串比较
void func5()
{
  cout << "----------------- string compare ---------------------" << endl;
  string s1 = "abcde";
  string s2 = "ab";
  int res = s1.compare(s2);
  cout << "s1 = " << s1 << " s2 = " << s2 << " s1.compare(s2): " << res << endl; 

}

// 字符串存取
void func6()
{
  cout << "----------------- string read/write ---------------------" << endl;
  string s1 = "abcdefg";
  char c = s1[3];
  cout << "s1 = " << s1 << " s1[3] = " << c << endl; 

  s1.at(0) = 'F';
  cout << "s1 = " << s1 << " s1.at(0) = 'F' -> = " << s1 << endl; 

}

// 字符串插入与删除
void func7()
{
  cout << "----------------- string insert/erase ---------------------" << endl;
  string s1 = "abcdefg";
  string s2 = s1.insert(2, "ABCD");
  cout << "s1 = " << s1 << " string s2 = s1.insert(2, ABCD); -> = " << s2 << endl; 

  string s3 = s1.erase(0, 2);
  cout << "string s3 = s1.erase(0, 2); -> = " << s3 << endl; 
}

// 子串
void func8()
{
  cout << "----------------- string insert/erase ---------------------" << endl;
  string s1 = "abcdefg";
  string s11 = s1.substr(0, 3);
  cout << "s1 = " << s1 << " string s11 = s1.substr(0, 3); -> = " << s11 << endl; 


}

int main()
{
  func1();
  func2();
  func3();
  func4();
  func5();
  func6();
  func7();
  func8();

  return 0;
}